﻿package ygg.printer
{
	import j.sus2maj7.printer.*;
	import j.sus2maj7.context.*;
	import j.sus2maj7.util.*;
	import flash.utils.ByteArray;
	
	import ygg.encoding.swf.structure.*;
	import ygg.encoding.swf.abc.*;
	import ygg.encoding.swf.abc.structure.*;
	import ygg.encoding.swf.abc.constant.*;
	import ygg.encoding.swf.tag.*
	
	public class SlotInfoPrinter extends AbstractPrinter
	{
		
		public function SlotInfoPrinter()
		{
			
		}
		
		override public function printToString(o:*, context:IContext=null):String
		{
			return printToStringB(o, context).toString();
		}
		override public function printToStringB(o:*, context:IContext=null):StringBuilder
		{
			var mi:SlotInfo = o as SlotInfo;
			
			return print(mi, AbcContext(context.vars.abcContext), PrinterContext(context) );
		}
		public function format(si:SlotInfo):String
		{
			return (isPrivate(si.name)?'private ': 'public ') + TraitKind.getName(si.kind) + ' '+ si.name + ":" + si.type +
				(si.value !== undefined ? (" = " + (si.value is String ? ('"'+si.value+'"') : si.value)) : "") +';'
		}
		
		
		private function print(si:SlotInfo, context:AbcContext, pc:PrinterContext ):StringBuilder
		{
			var cPool:ConstantPool = context.constantPool;
			var sb:StringBuilder = (pc.sb == null) ? new StringBuilder() : pc.sb;
			var attr:String = pc.vars.attr || '';
			var indent:String = pc.indent || '';
			var tab:String = pc.tab || '    ';
			
			if (sb == null)
			{
				sb = new StringBuilder();
			}
			sb.append('/* start sip */\n');
			if (si.kind == TraitKind.CONST || si.kind == TraitKind.SLOT)
			{
				if (si.metadata)
				{
					for each (md in si.metadata)
					{
						sb.append(indent + md + "\n");
					}
				}
				
				sb.append(indent + "// slot_id " + si.id + "\n");
				sb.append(indent + attr + format(si) + "\n");
				sb.append('/* end sip1 */');
				return sb;
			}
			
			// else, class
			
			var ct:TraitInfo = si.value
			var it:TraitInfo = ct.itraits
			
			var md:*;
			if (si.metadata)
			{
				for each (md in si.metadata)
				{
					sb.append(indent + md + "\n")
				}
			}
			
			//DO IMPORTS HERES
			
			var def:String = (isPrivate(si.name)?'private ': 'public ')
			
			if (i.flags & InstanceFlag.CLASS_INTERFACE)
			{
				def += "interface "
			}
			else
			{
				
				
				if (!(i.flags & InstanceFlag.CLASS_SEALED))
				{
					def += "dynamic ";
				}
				
				if (i.flags & InstanceFlag.CLASS_FINAL)
				{
					def += "final ";
				}
				
				def += "class ";
			}
			var packageName:String = getPackage(si.name);
			//package
			sb.append('package ' + packageName + '\n{\n' );
			indent += tab;
			sb.append(indent + attr + def + cleanClass(si.name) + " extends " + i.base + "\n");
			
			var oldIndent:String = indent;
			
			indent += tab;
			
			if (i.interfaces.length > 0)
			{
				sb.append(indent + "implements " + i.interfaces + "\n");
			}
			
			sb.append(oldIndent + "{\n");
			
			var ipf:IPrinterFactory = new AbcPrinterFactory()
			var mip:MethodInfoPrinter = new MethodInfoPrinter();
			
			pc.indent = indent;
			pc.vars.attr = 'static ';
			//ct.ini.dump(abc, indent, "static "); //methodInfo
			sb.append( mip.printToString( ct.init, pc) );
			
			pc.indent = indent;
			pc.vars.attr = '';
			//i.ini.dump(abc, indent); //methodInfo
			sb.append( mip.printToString(i.init, pc ) );
			var mi:*;
			var ip:IPrinter;
			
			pc.indent = indent;
			pc.vars.attr = '';
			//i.dump(abc, indent); //traitsinfo
			//tip.printToString( it);
			sb.append('/*'+i.base+'*/');
			for each (mi in i.members)
			{
				ip = ipf.getPrinter(mi);
				sb.append( ip.printToString(mi, pc) );
				
				
				//break;
				//writeStringToFile(context, File(context.vars.classDir).resolvePath(path));
			}
			
			pc.indent = indent;
			pc.vars.attr = 'static ';
			//ct.dump(abc, indent, "static "); //traitsinfo
			//tip.printToString( ct);
			for each (mi in ct.members)
			{
				ip = ipf.getPrinter(mi);
				sb.append( ip.printToString(mi, pc) );
				
				
				//break;
				//writeStringToFile(context, File(context.vars.classDir).resolvePath(path));
			}
			
			
			
			sb.append('\n'+oldIndent + "}\n}\n");
			sb.append('/* end sip */\n');
			return sb;
			
		}
		private function cleanClass(s:String):String
		{
			var j:int;
			var rs:String = s;
			if ( (j = s.lastIndexOf('::')) > -1)
				rs = s.substr(j + 2 );
			if ( (j = s.lastIndexOf('>')) > -1)
				rs = 'Vector_' + rs.substr(0, rs.length - 1);
			return rs;
		}
		private function getPackage(s:String):String
		{
			var j:int;
			var rs:String = '';
			if ( (j = s.lastIndexOf('::')) > -1)
				rs = s.substr(0, j );
			return rs;
		}
		private function isPrivate(s:String):Boolean
		{
			return (s.indexOf('private::') == 0);
		}
	}
}